package org.dromara.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.BusinessException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.config.SystemInfoConfig;
import org.dromara.system.constant.MachineConstant;
import org.dromara.system.domain.SimCard;
import org.dromara.system.domain.bo.AllocateSimCardByIccIdBo;
import org.dromara.system.domain.bo.FreshenIccIdBo;
import org.dromara.system.domain.bo.SimCardBo;
import org.dromara.system.domain.bo.StopOrRestartSimCardBo;
import org.dromara.system.domain.vo.IccIdInfoVo;
import org.dromara.system.domain.vo.SimCardStatusCountVo;
import org.dromara.system.domain.vo.SimCardVo;
import org.dromara.system.domain.vo.SingleIccIdInfoReqVo;
import org.dromara.system.listener.AllocateSimCardByFileListener;
import org.dromara.system.mapper.SimCardMapper;
import org.dromara.system.service.ISimCardService;
import org.dromara.system.service.impl.permission.PermissionBaseService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * 流量卡Service业务层处理
 *
 * @author Lion Li
 * @date 2025-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SimCardServiceImpl extends ServiceImpl<SimCardMapper, SimCard>
    implements ISimCardService {

    //查询单条iccId卡信息
    private final static String QUERY_USER_BASIC_INFO_PATH = "https://apizs.eptok.com//hz/queryUserBasicInfo";
    private final String STOP_OR_RESTART_SIM_CARD = "https://apizs.eptok.com/ajax/StopOpenOne";

    private final SystemInfoConfig systemInfoConfig;


//    public static void main(String[] args) throws ParseException {
//        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        String string = "2025-07-25 00:00:00";
//        Date parse = formatter.parse(string);
//        System.out.println(string);
//    }

    /**
     * 查询流量卡
     *
     * @param id 主键
     * @return 流量卡
     */
    @Override
    public SimCardVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询流量卡列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 流量卡分页列表
     */
    @Override
    public TableDataInfo<SimCardVo> queryPageList(SimCardBo bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        if (ObjectUtil.notEqual(userId, MachineConstant.ADMIN)) {
            bo.setCurrentUserId(userId);
        }
        IPage<SimCardVo> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        IPage<SimCardVo> list = baseMapper.findAll(page, bo);
        return TableDataInfo.build(list);
    }

    @Override
    public TableDataInfo<SimCardVo> listReception(SimCardBo bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        if (ObjectUtil.notEqual(userId, MachineConstant.ADMIN)) {
            bo.setCurrentUserId(userId);
        }
        IPage<SimCardVo> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        IPage<SimCardVo> list = baseMapper.findAll(page, bo);
        return TableDataInfo.build(list);
    }

    @Override
    public SimCardStatusCountVo querySimCardDistinguishStatus(SimCardBo bo) {
        Long userId = LoginHelper.getUserId();
        if (ObjectUtil.notEqual(userId, MachineConstant.ADMIN)) {
            bo.setCurrentUserId(userId);
        }
        List<SimCardVo> simCardVoList = baseMapper.findAll(bo);
        int totalSize = simCardVoList.size();
        long closureCount = simCardVoList.stream()
            .filter(simCard -> StrUtil.equals("销户", simCard.getStatus())).count();
        //上月到期
        DateTime lastMonthStart = DateUtil.beginOfMonth(DateUtil.lastMonth());
        DateTime lastMonthEnd = DateUtil.endOfMonth(DateUtil.lastMonth());
        long lastMonthCount = simCardVoList.stream()
            .filter(t -> ObjectUtil.isNotNull(t.getExpireTs()))
            .filter(t -> t.getExpireTs().after(lastMonthStart) && t.getExpireTs().before(lastMonthEnd)).count();

        //本月到期
        DateTime currentMonthStart = DateUtil.beginOfMonth(DateUtil.date());
        DateTime currentMonthEnd = DateUtil.endOfMonth(DateUtil.date());
        long currentMonthCount = simCardVoList.stream()
            .filter(t -> ObjectUtil.isNotNull(t.getExpireTs()))
            .filter(t -> t.getExpireTs().after(currentMonthStart) && t.getExpireTs().before(currentMonthEnd)).count();

        //未到期
        long unexpiredCount = simCardVoList.stream()
            .filter(t -> ObjectUtil.isNotNull(t.getExpireTs()))
            .filter(t -> t.getExpireTs().after(DateUtil.date())).count();
        return SimCardStatusCountVo.builder()
            .totalSize(totalSize)
            .closureCount(closureCount)
            .lastMonthCount(lastMonthCount)
            .currentMonthCount(currentMonthCount)
            .unexpiredCount(unexpiredCount)
            .build();
    }

    @Override
    public Boolean batchFreshen(FreshenIccIdBo bo) {
        bo.getIccIds().forEach(t -> {
            Boolean queryIccIdInfo = queryIccIdInfo(t);
        });
        return Boolean.TRUE;
    }

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH");
        String formattedDate = sdf.format(DateUtil.date());
        String token = SecureUtil.md5("18707156547".concat(formattedDate));
        String random = RandomUtil.randomString(9);
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("Account", "18707156547");
        hashMap.put("Password", SecureUtil.md5("1234qwer@"));
        hashMap.put("version", "V2");
        hashMap.put("Token", token);
        hashMap.put("ICCID", "89860470192290249793");
        hashMap.put("OrderNumber", random);
        hashMap.put("Name", "武汉智寰信息");
        String post = HttpUtil.get("https://apizs.eptok.com/hz/numberRenew", hashMap);
        System.out.println(post);
        SingleIccIdInfoReqVo singleIccIdInfoReqVo = JSONUtil.toBean(post, SingleIccIdInfoReqVo.class);

//        String post = HttpUtil.get("https://apizs.eptok.com/api/queryCustomerBalance?23110402556749");
//        System.out.println(post);

    }

    @Override
    public Boolean stopOrRestartSimCard(StopOrRestartSimCardBo bo) {
        StringBuilder failureMsg = new StringBuilder();
        bo.getIccIds().forEach(t -> {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH");
            String formattedDate = sdf.format(DateUtil.date());
            String token = SecureUtil.md5(systemInfoConfig.getAccount().concat(formattedDate));
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("Account", systemInfoConfig.getAccount());
            hashMap.put("Password", SecureUtil.md5(systemInfoConfig.getPassword()));
            hashMap.put("Token", token);
            hashMap.put("ICCID", t);
            hashMap.put("Name", systemInfoConfig.getName());
            hashMap.put("Action", bo.getAction());
            String post = HttpUtil.get(STOP_OR_RESTART_SIM_CARD, hashMap);
            SingleIccIdInfoReqVo singleIccIdInfoReqVo = JSONUtil.toBean(post, SingleIccIdInfoReqVo.class);
            if (!StrUtil.equals(singleIccIdInfoReqVo.getResultCode(), "0")) {
                String resultDesc = singleIccIdInfoReqVo.getResultDesc();
                failureMsg.append("<br/>").append(t).append(":").append(resultDesc);
            }
            queryIccIdInfo(t);
        });
        BusinessException.isTrue(StrUtil.isNotBlank(failureMsg.toString()), failureMsg.toString());
        return Boolean.TRUE;
    }


    /**
     * 新增流量卡
     *
     * @param bo 流量卡
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(SimCardBo bo) {
        SimCard add = MapstructUtils.convert(bo, SimCard.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改流量卡
     *
     * @param bo 流量卡
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(SimCardBo bo) {
        SimCard update = MapstructUtils.convert(bo, SimCard.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SimCard entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除流量卡信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            List<SimCard> list = lambdaQuery().in(SimCard::getId, ids).list();
            List<SimCard> simCardList = list.stream().filter(t -> ObjectUtil.isNotNull(t.getCurrentUserId())).toList();
            BusinessException.notEmpty(simCardList, "存在已分配的机器！");
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public Boolean queryIccIdInfo(String iccId) {
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("ICCID", iccId);
        String post = HttpUtil.get(QUERY_USER_BASIC_INFO_PATH, hashMap);
        log.info("{}基本信息={}", iccId, JSONUtil.toJsonStr(post));
        SingleIccIdInfoReqVo singleIccIdInfoReqVo = JSONUtil.toBean(post, SingleIccIdInfoReqVo.class);
        if (StrUtil.equals(singleIccIdInfoReqVo.getResultCode(), "0")
            && StrUtil.equals(singleIccIdInfoReqVo.getResultMessage(), "OK")) {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            IccIdInfoVo iccIdInfoVo = JSONUtil.toBean(singleIccIdInfoReqVo.getResultData(), IccIdInfoVo.class);
            try {
                UpdateWrapper<SimCard> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda().eq(SimCard::getIccId, iccId);
                updateWrapper.lambda().set(SimCard::getNumber, iccIdInfoVo.getNumber());
                updateWrapper.lambda().set(SimCard::getStatus, iccIdInfoVo.getStatus());
                updateWrapper.lambda().set(SimCard::getPackageId, iccIdInfoVo.getPackageID());
                updateWrapper.lambda().set(SimCard::getTotalInternetTraffic, iccIdInfoVo.getTotal());
                updateWrapper.lambda().set(SimCard::getUserInternetTraffic, iccIdInfoVo.getUse());
                updateWrapper.lambda().set(SimCard::getSurplusInternetTraffic, iccIdInfoVo.getSurplus());
                updateWrapper.lambda().set(SimCard::getValidLength, iccIdInfoVo.getValidLength());
                updateWrapper.lambda().set(SimCard::getValidLengthZ, iccIdInfoVo.getValidLengthZ());
                if (StrUtil.isNotBlank(iccIdInfoVo.getCreateTS())) {
                    updateWrapper.lambda().set(SimCard::getCreateTs, formatter.parse(iccIdInfoVo.getCreateTS()));
                }
                if (StrUtil.isNotBlank(iccIdInfoVo.getActiveTS())) {
                    updateWrapper.lambda().set(SimCard::getActiveTs, formatter.parse(iccIdInfoVo.getActiveTS()));
                }
                if (StrUtil.isNotBlank(iccIdInfoVo.getCancelTS())) {
                    updateWrapper.lambda().set(SimCard::getCancelTs, formatter.parse(iccIdInfoVo.getCancelTS()));
                }
                if (StrUtil.isNotBlank(iccIdInfoVo.getStopTS())) {
                    updateWrapper.lambda().set(SimCard::getStopTs, formatter.parse(iccIdInfoVo.getStopTS()));
                }
                if (StrUtil.isNotBlank(iccIdInfoVo.getExpireTS())) {
                    updateWrapper.lambda().set(SimCard::getExpireTs, formatter.parse(iccIdInfoVo.getExpireTS()));
                }
                baseMapper.update(updateWrapper);
            } catch (ParseException e) {
                log.info("{}查询SIM信息失败！", iccId);
            }
        }
        return Boolean.TRUE;
    }

    @Override
    public Boolean importMachineByIccId(SimCardBo simCardBo) {
        simCardBo.setUserId(LoginHelper.getUserId());
        Boolean insert = insertByBo(simCardBo);
        queryIccIdInfo(simCardBo.getIccId());
        return insert;
    }

    @Override
    public Boolean allocateSimCardByIccId(AllocateSimCardByIccIdBo bo) {
        return allocateSimCardCommon(bo.getIccIds(), bo.getCurrentUserId(), bo.getReNewNum());
    }

    @Override
    public Boolean allocateSimCardByFile(MultipartFile file, Long currentUserId, Integer reNewNum) {
        try {
            ExcelResult<SimCardVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), SimCardVo.class, new AllocateSimCardByFileListener());
            List<SimCardVo> list = excelResult.getList();
            if (CollUtil.isNotEmpty(list)) {
                List<String> iccIdList = list.stream().map(SimCardVo::getIccId).toList();
                allocateSimCardCommon(iccIdList, currentUserId, reNewNum);
            }
        } catch (Exception e) {
            BusinessException.isTrue(Boolean.TRUE, e.getMessage());
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }


    public Boolean allocateSimCardCommon(List<String> iccIds, Long currentUserId, Integer reNewNum) {
        List<SimCard> list = lambdaQuery().in(SimCard::getIccId, iccIds).list();
        List<SimCard> simCardList = list.stream().filter(t -> ObjectUtil.isNotNull(t.getCurrentUserId())).toList();
        BusinessException.notEmpty(simCardList, "列表存在已分配的机器！");
        return lambdaUpdate()
            .set(SimCard::getCurrentUserId, currentUserId)
            .set(SimCard::getRenewNum, reNewNum)
            .in(SimCard::getIccId, iccIds)
            .update();
    }

}
